package com.mastercard.auth

import org.apache.commons.codec.digest.DigestUtils
import org.apache.shiro.SecurityUtils
import org.apache.shiro.authc.UsernamePasswordToken
import org.apache.shiro.authc.AuthenticationException
import org.apache.shiro.web.util.WebUtils
import cr.co.arquetipos.crypto.Blowfish

import com.mastercard.auth.User
import com.mastercard.common.constants.CommonConstants;
import java.net.URLEncoder
class UserController {
	def profileService
    def scaffold = true
	def grailsApplication
	def password = "se19team2s"
	def mailService

    def show() {
        if (!params.id) {
            render status: 404, text: "No ID specified"
            return
        }

        def user
        if (params.id.isLong()) {
            user = User.get(params.id)
        }
        else {
            user = User.findByLogin(params.id)
        }

        if (!user) {
            render status: 404, text: "No user found with ID '${params.id}'"
            return
        }

        [userInstance: user]
    }

    def update(Long id) {
        def user = User.get(id)

        if(user) {
            bindData user, params, [exclude: ["permissions"]]
            setPermissionsFromString user, params.permissions

            if(!user.save(flush:true)) {
               render view:"edit", model:[userInstance:user]
            }
            else {
               redirect action:"show", id: user.id
            }
        } else {
            redirect action:"list"
        }   
    }

    def passwordReminder() {
        if(request.method == 'POST') {
            def user = User.findByLogin(params.login)
            if(user && user.login!='admin') {
                def newPassword = randomPass()
                user.password = DigestUtils.sha256Hex(newPassword)
                user.save()
//                mailService.sendMail {
//                    from "wiki@grails.org"
//                    to user.email
//                    title "Grails.org password reset"
//                    body "Your password has been reset. Please login with the following password: ${newPassword}"
//                }
            }
            else {
                flash.message = "Username not found"
            }
        }
    }

//    def profile() {
//        def userInfo = UserInfo.findByUser(request.user)
//        if(request.method == 'POST') {
//            if(!userInfo) userInfo = new UserInfo(user:request.user)
//            userInfo.properties = params
//            userInfo.save()
//            if(params.password) {
//                request.user.password = DigestUtils.shaHex(params.password) 
//                request.user.save()
//            }
//        }
//        return [user:request.user, userInfo:userInfo]
//
//    }
	
	def smsActivate(){
		log.info "sms key  ${params.key}"
		def user = SecurityUtils.subject.session.getAttribute(CommonConstants.LOGIN_USER)
		List activationList = user.userActivations;
		if(activationList == null || activationList.size() == 0){
			println "no activation list"
		}else{
			def ua = activationList.get(0)
			println "userActivation ${ua.key}"
			if(params.key == ua.key){
				user.refresh()
				user.status = User.Status.LIVE
				profileService.saveProfile(user)
				println "user live"
				redirect (controller: "dashboard", action: "dashboard")
			}
		}
	}
	def sendSMSActivationCode(){
		def renderParams = [ model:[originalURI:params.originalURI] ]
		def user = SecurityUtils.subject.session.getAttribute(CommonConstants.LOGIN_USER)
		Random random = new Random()
		def otp = random.nextInt(1000000) 
		renderParams.template = "activationForm"
		renderParams.model.message= "sms send ${otp} to ${user.mobile}"
		def data = new URL("http://137.132.247.154:8888/SMS/send.aspx?rep=${user.mobile}&msg=OTP-${otp}").getText()
		println "data =  ${data}"
		def userActivation = new UserActivation(key:otp, createDt:new Date()).save(flush: true)
		user.refresh()
		user.addToUserActivations(userActivation)
		profileService.saveProfile(user)
		renderParams.model.user=user
		render (renderParams)
	}
	def emailActivate(){
		log.info "value ${params.key}"
		def decrypt_value = (Blowfish.decryptBase64(params.key, password))
		log.info "value = ${decrypt_value}"
		String [] username_password = decrypt_value.split("&")
		def authToken = new UsernamePasswordToken(username_password[0],username_password[1]);
		try {
			SecurityUtils.subject.login(authToken)
			def user = SecurityUtils.subject.session.getAttribute(CommonConstants.LOGIN_USER)
			user.status = User.Status.PENDING_PHONE_ACTIVATION
			profileService.saveProfile(user)
			println "mobile ${user.mobile}  ${user.login}"
			chain(action: "pendingSMSActivation", model:[user:user])
			log.info "activated"
		} catch (AuthenticationException ex){
			log.info "active failure for user '${params.login}'."
		}
	}
	
    def register(){
        def renderParams = [ model:[originalURI:params.originalURI, async:request.xhr] ]
        
        if(request.xhr)
            renderParams.template = "registerForm"
        else
            renderParams.view = "register"

        if(request.method == 'POST') {
            if (!params.login) {
                log.warn "'login' not provided during registration - probably a spam bot."
                renderParams.model.message= "You must provide a login!"
                render(renderParams)
                return
            }

            def user = User.findByLogin(params.login)
            if(user) {

                renderParams.model.message= "auth.user.already.exists"
                render(renderParams)
            }
            else if(params.password != params.password2) {
                    renderParams.model.message= "auth.password.mismatch"
                    render(renderParams)
            }
            else {
				Date now = new Date();
				//Address address = new Address(addressType:params.addressType, addressLine1:params.addressLine1)
                user = new User(login:params.login, password: (params.password ? DigestUtils.sha256Hex(params.password) : null), email:params.email, dateCreated:now, lastUpdated:now, lastUpdatedBy:params.login, status:User.Status.PENDING_EMAIL_ACTIVICATION, mobile:params.mobile, gender:params.gender, name:params.name)
                  .addToRoles(Role.findByName(Role.CUSTOMER))
						//grailsAttributes.getApplicationContext().getResource("/relative/path/").getFile().toString()
			    def appURL = grailsApplication.config.grails.appURL
				profileService.saveProfile(user)
				
				String encrypted_value = URLEncoder.encode(Blowfish.encryptBase64("${params.login}&${params.password}", password), "ISO-8859-1")
				
					
				String activationURL = "${appURL}activate/${encrypted_value}"
				println "activationURL = ${activationURL}"
				renderParams.model.message= "Registeration Sussceesul! <br/> an activation link will send your email box. <br/> for SIT use below link <br/>  ${activationURL}"
				mailService.sendMail {
					to user.email
					from "mpems.mastercard@gmail.com"
					subject "MasterCard MPEMS registration"
					body "Dear user \n ${activationURL}" 
				 }
				render(renderParams)
				//Util.sendEmail({user.email}, "MasterCard MPEMS account activation", activationURL)
            }
        }
        else {
            render(renderParams)
        }

    }
	def pendingEmailActivation(){}
	def pendingSMSActivation(){
		def user = SecurityUtils.subject.session.getAttribute(CommonConstants.LOGIN_USER)
	}
	def postRegist(){}
    def logout() {
        SecurityUtils.subject.logout()
        redirect(uri:"/")
    }

    def login() {
        if(request.method == 'POST') {
            def authToken = new UsernamePasswordToken(params.login, params.password)
            // Support for "remember me"
            if (params.rememberMe) {
                authToken.rememberMe = true
            }
            // If a controller redirected to this page, redirect back
            // to it. Otherwise redirect to the root URI.
            def targetUri = params.originalURI ?: "/"
            
            // Handle requests saved by Shiro filters.
            def savedRequest = WebUtils.getSavedRequest(request)
            if (savedRequest) {
                targetUri = savedRequest.requestURI - request.contextPath
                if (savedRequest.queryString) targetUri = targetUri + '?' + savedRequest.queryString
            }
        
            try {
                SecurityUtils.subject.login(authToken)
				def user = SecurityUtils.subject.session.getAttribute(CommonConstants.LOGIN_USER)
				if(user.status == User.Status.PENDING_EMAIL_ACTIVICATION){
					renderParams.model.message= "Account NOT Activate yet"
					render(renderParams)
				}else if(user.status == User.Status.PENDING_PHONE_ACTIVATION){
					chain(action: "pendingSMSActivation", model:[user:user])
				} else{
                	log.info "Redirecting to '${targetUri}'."
					redirect(uri: targetUri)
				}
            } catch (AuthenticationException ex){
                log.info "Authentication failure for user '${params.username}'."
                if(request.xhr) {
                    params.remove 'password'
                    render(template:"loginForm", model:[originalURI:params.remove('originalURI'),
                                                        update: params._ul,
                                                        async:true,
                                                        message:"auth.invalid.login"])
                } else {
                    flash.message = "Invalid username and/or password"

                    redirect(action: 'login', params: [ username: params.username, originalURI:params.originalURI ])
                }
            }
        } else {            
            render(view:"login", model: [originalURI:params.originalURI])
        }
    }

    def unauthorized()  {}

    protected String randomPass() {
        UUID uuid = UUID.randomUUID()
        uuid.toString()[0..7]
    }

    protected setPermissionsFromString(user, String newlineSeparatedPermissions) {
        newlineSeparatedPermissions = newlineSeparatedPermissions?.trim()
        def perms = !newlineSeparatedPermissions ? [] : (newlineSeparatedPermissions.split(/\s*[\n;]\s*/) as List)

        // Take the simple approach: clear the list and re-add all declared permissions.
        if (user.permissions == null) {
            user.permissions = perms
        }
        else {
            user.permissions.clear()
            user.permissions.addAll perms
        }
    }
}

